package com.wyman.beans.factory.support;

import com.wyman.beans.BeanException;
import com.wyman.beans.factory.FactoryBean;
import com.wyman.beans.factory.config.BeanDefinition;
import com.wyman.beans.factory.config.BeanPostProcessor;
import com.wyman.beans.factory.config.ConfigurableBeanFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author 李伟民
 * @Description DateTime 2024/11/25 01:43
 */
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    //12.11 因为继承了ConfigurableBeanFactory 所以要实现添加BeanPostProcessor 使用ArrayList存储所有的BeanPostProcessor 后面的注册动作和apply动作都是读写这个列表
    private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();

    //模板设计模式 定义容器中获取bean的逻辑 但不负责逻辑中具体方法实现
    @Override
    public Object getBean(String beanName)  {
        return doGetBean(beanName,null);
    }
    //获取bean时传递参数 是入口
    @Override
    public Object getBean(String beanName, Object[] args) {
     return doGetBean(beanName,args);
    }

    public <T> T getBean(String beanName,Class<T> requireType) {
        return (T)getBean(beanName);
    }

    public <T> T doGetBean(String name,Object[] args){

        Object sharedInstance = getSingleton(name);
        if(sharedInstance!=null){
            return (T)getObjectFormBeanInstance(sharedInstance,name);
        }
        BeanDefinition beanDefinition = getBeanDefinition(name);
        Object bean = null;
        try {
            //这里创建的是factory bean,同时将factory bean加入到单例bean的Map中 再通过后面调用 getObjectFormBeanInstance实现
           bean = createBean(name,beanDefinition,args);

        } catch (Exception e) {
            System.out.println("问题是"+e.toString());
            System.out.println(bean.toString());
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return (T)getObjectFormBeanInstance(bean,name);
    }


    //12.14 增加对factory bean的支持 如果是这种类型的bean 在获取时 会调用这个bean接口的获取bean的方法 返回由这个bean创建的bean
    private Object getObjectFormBeanInstance(Object beanInstance,String beanName){
        //不需要递归创建bean对象
        if(!(beanInstance instanceof FactoryBean)){
            return beanInstance;
        }
        Object object = getCachedObjectFromFactoryBean(beanName);
        if(object==null){
            FactoryBean<?> factoryBean = (FactoryBean<?>) beanInstance;
            object = getObjectFromFactoryBean(factoryBean, beanName);
        }
        return object;
    }


    protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeanException;

    //负责实现 真正创建bean
    protected abstract Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws Exception;

    //12.11 新增添加bean处理器的功能
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
        //增加新bean处理器时 需要先删除之前存在的 同样的处理器 难道是存在同一个处理器对象 添加之后 在容器运行过程中 又修改了 需要重新添加 为了避免原来的处理器发挥作用  存疑 不确定
        this.beanPostProcessors.remove(beanPostProcessor);
        //熙增处理器
        this.beanPostProcessors.add(beanPostProcessor);
    }

    public List<BeanPostProcessor> getBeanPostProcessors(){
        return this.beanPostProcessors;
    }
}
